From: Jimi Xenidis Date: Wed, 13 Sep 2006 22:41:11 +0000 (-0400) Subject: [POWERPC][XEN] Track pages correctly X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15658^2~68 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22?a=commitdiff_plain;h=73bf5f40ccce04c1c4409047e1773e1cefc4d86d;p=xen.git [POWERPC][XEN] Track pages correctly The following patch tracks and frees pages correctly. It solves the problem where a foreign mapping would zombie a domain because the refcnts remained. This involved: - implement relinquish_memory() for PowerPC - remove free_rma() since all pages get "relinquished" now. - foreign pages are get and put correctly Signed-off-by: Jimi Xenidis Signed-off-by: Hollis Blanchard --- diff --git a/xen/arch/powerpc/domain.c b/xen/arch/powerpc/domain.c index ff93bd1cc0..29bdd54ba8 100644 --- a/xen/arch/powerpc/domain.c +++ b/xen/arch/powerpc/domain.c @@ -242,10 +242,44 @@ void sync_vcpu_execstate(struct vcpu *v) return; } +static void relinquish_memory(struct domain *d, struct list_head *list) +{ + struct list_head *ent; + struct page_info *page; + + /* Use a recursive lock, as we may enter 'free_domheap_page'. */ + spin_lock_recursive(&d->page_alloc_lock); + + ent = list->next; + while ( ent != list ) + { + page = list_entry(ent, struct page_info, list); + + /* Grab a reference to the page so it won't disappear from under us. */ + if ( unlikely(!get_page(page, d)) ) + { + /* Couldn't get a reference -- someone is freeing this page. */ + ent = ent->next; + continue; + } + if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) + put_page_and_type(page); + + if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) + put_page(page); + + /* Follow the list chain and /then/ potentially free the page. */ + ent = ent->next; + put_page(page); + } + spin_unlock_recursive(&d->page_alloc_lock); +} + void domain_relinquish_resources(struct domain *d) { - free_rma(d); + relinquish_memory(d, &d->page_list); free_extents(d); + return; } void arch_dump_domain_info(struct domain *d) diff --git a/xen/arch/powerpc/mm.c b/xen/arch/powerpc/mm.c index cab7598917..46d6db2236 100644 --- a/xen/arch/powerpc/mm.c +++ b/xen/arch/powerpc/mm.c @@ -329,13 +329,6 @@ int allocate_rma(struct domain *d, unsigned int order) return 0; } -void free_rma(struct domain *d) -{ - if (d->arch.rma_page) { - free_domheap_pages(d->arch.rma_page, d->arch.rma_order); - } -} - ulong pfn2mfn(struct domain *d, ulong pfn, int *type) { ulong rma_base_mfn = page_to_mfn(d->arch.rma_page); diff --git a/xen/arch/powerpc/papr/xlate.c b/xen/arch/powerpc/papr/xlate.c index 805a0e6785..7a4da2c127 100644 --- a/xen/arch/powerpc/papr/xlate.c +++ b/xen/arch/powerpc/papr/xlate.c @@ -263,6 +263,7 @@ static void h_enter(struct cpu_user_regs *regs) BUG_ON(f == d); get_domain(f); + get_page(pg, f); } break; case PFN_TYPE_RMA: @@ -510,8 +511,10 @@ static void h_remove(struct cpu_user_regs *regs) struct page_info *pg = mfn_to_page(mfn); struct domain *f = page_get_owner(pg); - if (f != d) + if (f != d) { put_domain(f); + put_page(pg); + } } } diff --git a/xen/include/asm-powerpc/mm.h b/xen/include/asm-powerpc/mm.h index b54f904618..0f272286e0 100644 --- a/xen/include/asm-powerpc/mm.h +++ b/xen/include/asm-powerpc/mm.h @@ -154,7 +154,6 @@ static inline void put_page(struct page_info *page) while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) ); if ( unlikely((nx & PGC_count_mask) == 0) ) { - panic("about to free page: 0x%lx\n", page_to_mfn(page)); free_domheap_page(page); } } @@ -259,7 +258,6 @@ static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gmfn) #define mfn_to_gmfn(_d, mfn) (mfn) extern int allocate_rma(struct domain *d, unsigned int order_pages); -extern void free_rma(struct domain *d); extern uint allocate_extents(struct domain *d, uint nrpages, uint rma_nrpages); extern void free_extents(struct domain *d);